package Thread;

class  MyBlockingQueue{
    private String[] elems = null;
    //这个数组范围是[head,tail)
    //head 位置指向第一个元素,tail 指向数组最后一个元素的下一个元素
    private volatile int head = 0;
    private volatile int tail = 0;
    private volatile int size = 0;

    //阻塞队列的创建
    public MyBlockingQueue(int capacity){
        elems = new String[capacity];
    }

    //插入元素
    void put(String elem) throws InterruptedException{
        synchronized(this){
            while(size >= elems.length){
                //队列满了,后续再处理阻塞的情况
                this.wait();
            }
            //把新的元素放到tail所在的位置上
            elems[tail] = elem;
            tail++;
            if(tail >= elems.length){
                //到达末尾,就回到开头
                tail = 0; //这是双端队列,为了节省空间,如果头出了一个元素,tail指向开头可以继续插入元素,节省空间
            }
            //更新size的值
            size++;
            //唤醒下面 take 阻塞的 wait;
            this.notify();

        }
    }

    //取出元素
    String take() throws InterruptedException{
        synchronized(this){
            while(size == 0){
                //队列空了,后续再处理阻塞的情况
                this.wait();
            }
            //取出 head 指向的元素
            String result = elems[head];
            head++;
            if(head >= elems.length){
                head = 0;
            }
            // head = (head + 1 ) % elems.length;
            size--;
            // take 成功一个元素 , 就唤醒上面 put 中的 wait 操作
            this.notify();
            return result;
        }
    }
}

public class Demo31 {
    public static void main(String[] args) {
        MyBlockingQueue queue = new MyBlockingQueue(1000);

        //生产者
        Thread t1 = new Thread(() -> {
            try{
                int count = 1;
                while(true){
                    queue.put(count+"");
                    System.out.println("生产" + count);
                    //Thread.sleep(1000);
                    count++;
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        Thread t2 = new Thread(() -> {
            try{
                while(true){
                    String result = queue.take();
                    System.out.println("消费" + result);
                    Thread.sleep(1000);

                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        });

        t1.start();
        t2.start();
    }
}
